#include "log.hpp"
#include "Socket.hpp"
#include "tcp_server.hpp"
#include "Protocal.hpp"
#include <ctime>
#include <cassert>
using namespace std;

static void usage(const string &procname)
{
    cout << "\nusage: " << procname << " serverip serverport\n"
         << endl;
}
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        usage(argv[0]);
        exit(0);
    }
    string serverip = argv[1];
    uint16_t serverport = stoi(argv[2]);

    // 1. 创建客户端 socket 并连接服务器
    Sock sockfd;
    sockfd.Socket();
    bool r = sockfd.Connect(serverip, serverport);
    if (!r)
    {
        return 1;
    }

    // 2. 初始化随机数（用于生成随机 x、y、运算符）
    srand(time(nullptr) ^ getpid());
    string opers = "=-*/%=&~";
    int cnt = 1;
    string inbuffer_stream;// 存储服务器返回的字节流（可能包含多个报文）

    // 3. 循环 10 次，生成请求并处理结果
    while (cnt <= 10)
    {
        cout << "================第" << cnt << "次测试...================" << endl;
        ++cnt;

        // 3.1 生成随机请求数据
        int x = rand() % 100 + 1;
        usleep(1000);
        int y = rand() % 100;
        char oper = opers[rand() % opers.size()];

        // 3.2 构建 Request 对象并打印调试信息
        Request req(x, y, oper);
        req.debugPrint();// 如 "新请求构建完成：10+20=?"

        // 3.3 序列化 + 编码：准备发送给服务器的报文
        string package;
        req.serialize(&package);
        package = encode(package);// 加报文头（len\ncontent\n）

        cout << "new request: \n"
             << package;

        // 3.4 把报文写给服务器
        write(sockfd.get_fd(), package.c_str(), package.size());

        // 3.5 读取服务器返回的结果
        char buffer[128];// 接收缓冲区
        ssize_t n = read(sockfd.get_fd(), buffer, sizeof(buffer));
        if (n > 0)// 成功读取到数据
        {
            buffer[n] = '\0';
            inbuffer_stream += buffer; // 将读取到的数据拼接到缓冲区（处理粘包）"len""\n""result code""\n"
            cout << inbuffer_stream << endl;

            // 从缓冲区中解析出完整的响应内容
            string content;
            bool r = decode(inbuffer_stream, &content); // 解码，提取有效载荷 content = "result code"
            assert(r);

            // 反序列化响应内容，得到计算结果
            Response resp;
            r = resp.deserialize(content);// 将JSON字符串转为响应对象
            assert(r);

            resp.debugPrint();// 打印计算结果（如"result:30 code:0"）
        }
        cout << "============================================" << endl;
        sleep(1);
    }

    sockfd.Close();
    return 0;
}